using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Reflection;
using System.Windows.Forms;
using System.IO;
using WeifenLuo.WinFormsUI.Docking;
using UMLDesigner.Customization;
using UMLDesigner.Widgets;
using UMLDesigner.GUI;
using UMLDesigner.Page;

namespace UMLDesigner
{
	public partial class MainForm : Form
	{
		private bool m_bSaveLayout = true;
		private DeserializeDockContent m_deserializeDockContent;
		private PropertiesPanel m_propertyWindow = new PropertiesPanel();
		private Toolbox m_toolbox = new Toolbox();
		private UMLPage currentPage;

		public MainForm()
		{
			InitializeComponent();
			showRightToLeft.Checked = (RightToLeft == RightToLeft.Yes);
			RightToLeftLayout = showRightToLeft.Checked;
			m_deserializeDockContent = new DeserializeDockContent(GetContentFromPersistString);

			InitOption();
		}

		private void InitOption()
		{
			Option option = new Option();
			option.DefaultColors[Colors.CLASS_OUTLINE] = Color.FromArgb(95, 76, 126);
			option.DefaultColors[Colors.CLASS_FILL] = Color.FromArgb(181, 161, 212);
			Font font = new Font("Consolas", 12);
			option.DefaultFont = font;
			option.DefaultFontColor = Color.Black;
			option.SelectedLineColor = Color.Black;
			option.FocusedLineColor = Color.BlueViolet;
			option.SelectionRectangleTopLeftColor = Color.FromArgb(150, 0, 50, 160);
			option.SelectionRectangleBottomRightColor = Color.FromArgb(150, 200, 200, 255);
			option.NoteCornerColor = Color.FromArgb(230, 200, 30);
			option.NoteOutlineColor = Color.FromArgb(220, 170, 0);
			option.LineColor = Color.FromArgb(95, 76, 126);

			CurrentOption.Instance.Option = option;
		}

		private void menuItemExit_Click(object sender, System.EventArgs e)
		{
			Close();
		}

		private void menuItemPropertyWindow_Click(object sender, System.EventArgs e)
		{
			m_propertyWindow.Show(dockPanel);
		}

		private void menuItemToolbox_Click(object sender, System.EventArgs e)
		{
			m_toolbox.Show(dockPanel);
		}

		private void menuItemAbout_Click(object sender, System.EventArgs e)
		{
			AboutDialog aboutDialog = new AboutDialog();
			aboutDialog.ShowDialog(this);
		}

		private IDockContent FindDocument(string text)
		{
			if (dockPanel.DocumentStyle == DocumentStyle.SystemMdi)
			{
				foreach (Form form in MdiChildren)
					if (form.Text == text)
						return form as IDockContent;
				
				return null;
			}
			else
			{
				foreach (IDockContent content in dockPanel.Documents)
					if (content.DockHandler.TabText == text)
						return content;

				return null;
			}
		}

		private void menuItemNew_Click(object sender, System.EventArgs e)
		{
			UMLPage umlPage = CreateNewDocument();

			if (umlPage == null) return;
			if (dockPanel.DocumentStyle == DocumentStyle.SystemMdi)
			{
				umlPage.MdiParent = this;
				umlPage.Show();
			}
			else
			{
				umlPage.Show(dockPanel);
			}
			currentPage = umlPage;
		}

		private UMLPage CreateNewDocument()
		{
			NewFileDialog dlg = new NewFileDialog();
			UMLPage umlPage = null;

			if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
			{
				umlPage = new UMLPage();

				umlPage.Text = dlg.FileName;

				umlPage.Document = CreateNewDaigramDocument(dlg.SelectedDiagram);
				umlPage.Document.UMLPage = umlPage;
				m_toolbox.CurrentPage = umlPage;
			}
			return umlPage;
		}

		private Document CreateNewDaigramDocument(string name)
		{
			Document doc = null;

			switch(name)
			{
				case "Class Diagram":
					doc = new ClassDiagramDocument();
					break;
			}

			return doc;
		}

		private UMLPage CreateNewDocument(string text)
		{
			UMLPage dummyDoc = new UMLPage();
			dummyDoc.Text = text;
			return dummyDoc;
		}

		private void menuItemOpen_Click(object sender, System.EventArgs e)
		{
			OpenFileDialog openFile = new OpenFileDialog();

			openFile.InitialDirectory = Application.ExecutablePath;
			openFile.Filter = "rtf files (*.rtf)|*.rtf|txt files (*.txt)|*.txt|All files (*.*)|*.*" ;
			openFile.FilterIndex = 1;
			openFile.RestoreDirectory = true ;

			if(openFile.ShowDialog() == DialogResult.OK)
			{
				string fullName = openFile.FileName;
				string fileName = Path.GetFileName(fullName);

				if (FindDocument(fileName) != null)
				{
					MessageBox.Show("The document: " + fileName + " has already opened!");
					return;
				}

				UMLPage dummyDoc = new UMLPage();
				dummyDoc.Text = fileName;
				if (dockPanel.DocumentStyle == DocumentStyle.SystemMdi)
				{
					dummyDoc.MdiParent = this;
					dummyDoc.Show();
				}
				else
					dummyDoc.Show(dockPanel);
				try
				{
					//dummyDoc.FileName = fullName;
				}
				catch (Exception exception)
				{
					dummyDoc.Close();
					MessageBox.Show(exception.Message);
				}

			}
		}

		private void menuItemFile_Popup(object sender, System.EventArgs e)
		{
			if (dockPanel.DocumentStyle == DocumentStyle.SystemMdi)
			{
				menuItemClose.Enabled = menuItemCloseAll.Enabled = (ActiveMdiChild != null);
			}
			else
			{
				menuItemClose.Enabled = (dockPanel.ActiveDocument != null);
				menuItemCloseAll.Enabled = (dockPanel.DocumentsCount > 0);
			}
		}

		private void menuItemClose_Click(object sender, System.EventArgs e)
		{
			if (dockPanel.DocumentStyle == DocumentStyle.SystemMdi)
				ActiveMdiChild.Close();
			else if (dockPanel.ActiveDocument != null)
				dockPanel.ActiveDocument.DockHandler.Close();
		}

		private void menuItemCloseAll_Click(object sender, System.EventArgs e)
		{
			CloseAllDocuments();
		}

		private void CloseAllDocuments()
		{
			if (dockPanel.DocumentStyle == DocumentStyle.SystemMdi)
			{
				foreach (Form form in MdiChildren)
					form.Close();
			}
			else
			{
				for (int index = dockPanel.Contents.Count - 1; index >= 0; index--)
				{
					if (dockPanel.Contents[index] is IDockContent)
					{
						IDockContent content = (IDockContent)dockPanel.Contents[index];
						content.DockHandler.Close();
					}
				}
			}
		}

		private IDockContent GetContentFromPersistString(string persistString)
		{
			if (persistString == typeof(PropertiesPanel).ToString())
				return m_propertyWindow;
			else if (persistString == typeof(Toolbox).ToString())
				return m_toolbox;
			else
			{
				// DummyDoc overrides GetPersistString to add extra information into persistString.
				// Any DockContent may override this value to add any needed information for deserialization.

				string[] parsedStrings = persistString.Split(new char[] { ',' });
				if (parsedStrings.Length != 3)
					return null;

				if (parsedStrings[0] != typeof(UMLPage).ToString())
					return null;

				UMLPage dummyDoc = new UMLPage();
				if (parsedStrings[1] != string.Empty)
					//dummyDoc.FileName = parsedStrings[1];
				if (parsedStrings[2] != string.Empty)
					dummyDoc.Text = parsedStrings[2];

				return dummyDoc;
			}
		}

		private void MainForm_Load(object sender, System.EventArgs e)
		{
			string configFile = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "DockPanel.config");

			if (File.Exists(configFile))
				dockPanel.LoadFromXml(configFile, m_deserializeDockContent);
		}

		private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			string configFile = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "DockPanel.config");
			if (m_bSaveLayout)
				dockPanel.SaveAsXml(configFile);
			else if (File.Exists(configFile))
				File.Delete(configFile);
		}

		private void menuItemToolBar_Click(object sender, System.EventArgs e)
		{
			toolBar.Visible = menuItemToolBar.Checked = !menuItemToolBar.Checked;
		}

		private void menuItemStatusBar_Click(object sender, System.EventArgs e)
		{
			statusBar.Visible = menuItemStatusBar.Checked = !menuItemStatusBar.Checked;
		}

		private void toolBar_ButtonClick(object sender, System.Windows.Forms.ToolStripItemClickedEventArgs e)
		{
			if (e.ClickedItem == toolBarButtonNew)
				menuItemNew_Click(null, null);
			else if (e.ClickedItem == toolBarButtonOpen)
				menuItemOpen_Click(null, null);
			else if (e.ClickedItem == toolBarButtonPropertyWindow)
				menuItemPropertyWindow_Click(null, null);
			else if (e.ClickedItem == toolBarButtonToolbox)
				menuItemToolbox_Click(null, null);
		}

		private void menuItemNewWindow_Click(object sender, System.EventArgs e)
		{
			MainForm newWindow = new MainForm();
			newWindow.Text = newWindow.Text + " - New";
			newWindow.Show();
		}

		private void menuItemTools_Popup(object sender, System.EventArgs e)
		{
			menuItemLockLayout.Checked = !this.dockPanel.AllowEndUserDocking;
		}

		private void menuItemLockLayout_Click(object sender, System.EventArgs e)
		{
			dockPanel.AllowEndUserDocking = !dockPanel.AllowEndUserDocking;
		}

		private void CloseAllContents()
		{
			// we don't want to create another instance of tool window, set DockPanel to null
			m_propertyWindow.DockPanel = null;
			m_toolbox.DockPanel = null;

			// Close all other document windows
			CloseAllDocuments();
		}

		private void SetSchema(object sender, System.EventArgs e)
		{
			CloseAllContents();

			if (sender == menuItemSchemaVS2005)
				Extender.SetSchema(dockPanel, Extender.Schema.VS2005);
			else if (sender == menuItemSchemaVS2003)
				Extender.SetSchema(dockPanel, Extender.Schema.VS2003);

			menuItemSchemaVS2005.Checked = (sender == menuItemSchemaVS2005);
			menuItemSchemaVS2003.Checked = (sender == menuItemSchemaVS2003);
		}

		private void SetDocumentStyle(object sender, System.EventArgs e)
		{
			DocumentStyle oldStyle = dockPanel.DocumentStyle;
			DocumentStyle newStyle;
			if (sender == menuItemDockingMdi)
				newStyle = DocumentStyle.DockingMdi;
			else if (sender == menuItemDockingWindow)
				newStyle = DocumentStyle.DockingWindow;
			else if (sender == menuItemDockingSdi)
				newStyle = DocumentStyle.DockingSdi;
			else
				newStyle = DocumentStyle.SystemMdi;
			
			if (oldStyle == newStyle)
				return;

			if (oldStyle == DocumentStyle.SystemMdi || newStyle == DocumentStyle.SystemMdi)
				CloseAllDocuments();

			dockPanel.DocumentStyle = newStyle;
			menuItemDockingMdi.Checked = (newStyle == DocumentStyle.DockingMdi);
			menuItemDockingWindow.Checked = (newStyle == DocumentStyle.DockingWindow);
			menuItemDockingSdi.Checked = (newStyle == DocumentStyle.DockingSdi);
			menuItemSystemMdi.Checked = (newStyle == DocumentStyle.SystemMdi);
			toolBarButtonLayoutByCode.Enabled = (newStyle != DocumentStyle.SystemMdi);
			toolBarButtonLayoutByXml.Enabled = (newStyle != DocumentStyle.SystemMdi);
		}

		private void menuItemCloseAllButThisOne_Click(object sender, System.EventArgs e)
		{
			if (dockPanel.DocumentStyle == DocumentStyle.SystemMdi)
			{
				Form activeMdi = ActiveMdiChild;
				foreach (Form form in MdiChildren)
				{
					if (form != activeMdi)
						form.Close();
				}
			}
			else
			{
				foreach (IDockContent document in dockPanel.DocumentsToArray())
				{
					if (!document.DockHandler.IsActivated)
						document.DockHandler.Close();
				}
			}
		}

		private void menuItemShowDocumentIcon_Click(object sender, System.EventArgs e)
		{
			dockPanel.ShowDocumentIcon = menuItemShowDocumentIcon.Checked= !menuItemShowDocumentIcon.Checked;
		}

		private void showRightToLeft_Click(object sender, EventArgs e)
		{
			CloseAllContents();
			if (showRightToLeft.Checked)
			{
				this.RightToLeft = RightToLeft.No;
				this.RightToLeftLayout = false;
			}
			else
			{
				this.RightToLeft = RightToLeft.Yes;
				this.RightToLeftLayout = true;
			}
			showRightToLeft.Checked = !showRightToLeft.Checked;
		}

		private void exitWithoutSavingLayout_Click(object sender, EventArgs e)
		{
			m_bSaveLayout = false;
			Close();
			m_bSaveLayout = true;
		}

		private void OnEditUndo(object sender, EventArgs e)
		{
			currentPage.Document.Undo();
			currentPage.Invalidate();
		}

		private void OnEditRedo(object sender, EventArgs e)
		{
			currentPage.Document.Redo();
			currentPage.Invalidate();
		}

		private void dockPanel_ActiveDocumentChanged(object sender, EventArgs e)
		{
			currentPage = (UMLPage)dockPanel.ActiveDocument;
			m_toolbox.CurrentPage = currentPage;            
		}
	}
}